'use strict';

const {env} = require('./config')
// console.log('env', env)
const {nanoid:uuid} = require("nanoid");
// const { v4: uuid } = require("uuid");
// console.log('uuid ', uuid())

const express = require('express')
const router = require('./router')

// multipart/form-data
// const multer = require('multer')
// const { logger } = require('./utils/log');
// const expLogger  = require('./utils/log').expLogger;
const { ERROR_CODE,HttpError, DbError, CustomError } = require('./error');
const rspHelper = require('./utils/rsp');

const app = express()
app.locals.count    = 0;
app.locals.count404 = 0;
app.locals.countErr = 0;
app.use('/public',express.static('public'))
// application/json
app.use(express.json())
// application/x-www-form-urlencoded
// extended:false表示方法内部使用querystring模块处理请求参数的格式
// extended:true表示方法内部使用第三方模块qs处理请求参数的格式
app.use(express.urlencoded())

app.param('id', function (req, res, next, id) {
  req.id = id
  next();
});

// app.use(expLogger)
app.use(function(req,rsp,next){
  app.locals.count ++
  console.log(` ===> ${app.locals.count}(4:${app.locals.count404},e:${app.locals.countErr}) : ${req.method}  : ${req.url}`);
    next();
})
router(app);
// catch 404 and forward to error handler
app.use((req, rsp, next) => {
  // 404
  next(new CustomError(ERROR_CODE.NOT_FOUND.msg,ERROR_CODE.NOT_FOUND.code));
});

// https://www.jianshu.com/p/0293e0e89d8b
// 全局的unhandledRejection事件会优先处理这个错误，, Promise里用Catch处理是不会生效的。
// process.on('unhandledRejection', error => {
//   console.log('我帮你处理了', error.message);
// });
// 防止进程提前挂掉
process.on('uncaughtException', (err) => {
  console.log('app uncaughtException', err);
});
// error handler
app.use((err, req, rsp, next) => {
  app.locals.countErr ++
  if (ERROR_CODE.NOT_FOUND.code === err.code){
    app.locals.count404++
    console.log('==== app catch err', err.code);
  }else{
    console.log('==== app catch err', err.code,  err);
  }
  if (err instanceof DbError) {
  } else if (err instanceof HttpError) {
  } else if (err instanceof CustomError) {
  } else if (err instanceof Error) {
    // rsp 要处理 + 自定义的属性
    // mysql2 errr
      // console.log('e1',typeof e,e)
      // console.log('e1',e.name,e.message,e.stack)
      // 1.Error {
      //  errno: -4078,
      //  code: 'ECONNREFUSED',
      //  syscall: 'connect',
      //  address: '127.0.0.1',
      //  port: 3306,
      //  fatal: true
      // }
      // 2.Error {
      //  code: 'ER_PARSE_ERROR',
      //  errno: 1064,
      //  sql: 'select * from  where id=? limit 1',
      //  sqlState: '42000',
      //  sqlMessage: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where id=? limit 1' at line 1"
      // }
      // console.log('getConn error', e);
    if (err.errno) {
      const detail = Object.assign({},err)
      err = new DbError(err.code, err.address ? 1 : err.sql ? 2 : 0)
      err.detail = detail
    }
  } else {
    err = new CustomError(ERROR_CODE.UNDEFINED_ERROR.msg,ERROR_CODE.UNDEFINED_ERROR.code);
  }
  err.lang = req.query.lang || env.LANG || 'en'
  return rspHelper(rsp).err(err);
});

// module.exports = app
const port = env.PORT;
const server = require('http').createServer(app)
server.listen(port, () => {
  console.log(`app start on http://localhost:${port}`)
});

// this function is called when you want the server to die gracefully
// i.e. wait for existing connections
var gracefulShutdown = function () {
  console.log("==== Received kill signal, shutting down gracefully.");
  server.close(function () {
    console.log("==== Closed out remaining connections.");
    process.exit()
  });

  // if after
  setTimeout(function () {
    console.error("==== Could not close connections in time, forcefully shutting down");
    process.exit()
  }, 10 * 1000);
}

// listen for TERM signal .e.g. kill
process.on('SIGTERM', gracefulShutdown);
// listen for INT signal e.g. Ctrl-C
process.on('SIGINT', gracefulShutdown);